/*
 * mox_storage.c
 *
 *  Created on: Jul 12, 2010
 *      Author: jmonk
 */
#include <stdlib.h>
#include <xs1.h>
#include <print.h>
#include "mox.h"
#include "mox_slave.h"
#include "mox_storage.h"
#include "mox_module.h"

int all_storage_free(struct mox_storage *storage)
{
	int i;
	for (i = 0; i < storage->num; i++) {
		if (!storage_free(storage->mod[i])) return 0;
	}

	return 1;
}

int storage_free(struct mox_module *mod)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	int response;
	if (!msg) return 1;

	if (mox_req_com(mod->core_id, mod->mod_id)) {
		msg->content = NULL;
		msg->size = 0;
		msg->type = STORAGE_FREE;
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		mox_end_com(mod->core_id);
		if (msg) {
			response = msg->type;
			if (msg->content) free(msg->content);
			free(msg);
		}
	}

	return (response == STORAGE_FREE);
}

int lock_all_storage(struct mox_storage *storage)
{
	int i;
	for (i = 0; i < storage->num; i++) {
		if (lock_storage(storage->mod[i])) return 1;
	}

	return 0;
}

int lock_storage(struct mox_module *mod)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	int response;
	if (!msg) return 1;

	if (mox_req_com(mod->core_id, mod->mod_id)) {
		msg->content = NULL;
		msg->size = 0;
		msg->type = STORAGE_LOCK;
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		mox_end_com(mod->core_id);
		if (msg) {
			response = msg->type;
			if (msg->content) free(msg->content);
			free(msg);
		}
	}


	return !(response == STORAGE_ACK);
}

int unlock_all_storage(struct mox_storage *storage)
{
	int i;
	for (i = 0; i < storage->num; i++) {
		if (unlock_storage(storage->mod[i])) return 1;
	}

	return 0;
}

int unlock_storage(struct mox_module *mod)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	int response;
	if (!msg) return 1;

	msg->content = NULL;
	msg->size = 0;
	msg->type = STORAGE_UNLK;
	if (mox_req_com(mod->core_id, mod->mod_id)) {
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		mox_end_com(mod->core_id);
		if (msg) {
			response = msg->type;
			if (msg->content) free(msg->content);
			free(msg);
		}
	}

	return !(response == STORAGE_ACK);
}

int *read_storage(struct mox_module *mod, int addr, int n)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	int response;
	int *p = NULL;
	int i;

	if (!msg) return NULL;

	msg->content = (unsigned char *)malloc(2 * sizeof(unsigned));
	if (!msg->content) {
		free(msg);
		return NULL;
	}
	msg->size = 2 * sizeof(unsigned);
	msg->type = STORAGE_READ;
	((unsigned *)msg->content)[0] = addr;
	((unsigned *)msg->content)[0] = n;

	if (mox_req_com(mod->core_id, mod->mod_id)) {
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg->content);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		mox_end_com(mod->core_id);
		if (msg && (msg->type == STORAGE_ACK) && msg->content) {
			p = (int *)msg->content;
			free(msg);
		} else if (msg) {
			if (msg->content) free(msg->content);
			free(msg);
		}
	}

	return p;
}

int write_storage(struct mox_module *mod, int addr, int n, void *data)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	unsigned response;
	int i;

	if (!msg) return NULL;
	msg->content = (unsigned char *)malloc(sizeof(unsigned));
	if (!msg->content) {
		free(msg);
		return 1;
	}
	msg->size = sizeof(unsigned);
	((unsigned *)msg->content)[0] = addr;
	msg->type = STORAGE_WRTE;

	if (mox_req_com(mod->core_id, mod->mod_id)) {
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg->content);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		if (msg->content) free(msg->content);
		if (msg && (msg->type == STORAGE_ACK)) {
			msg->content = (unsigned char *)data;
			msg->size = n;
			msg->type = STORAGE_WRTE;
			mox_comm_msg_send_thd(mod->core_id, *msg);
			msg->content = NULL;
		}
		if (msg) {
			free(msg);
		}
		msg = mox_comm_msg_recv_thd(mod->core_id);

		mox_end_com(mod->core_id);

	}
	if (msg) {
		response = msg->type;
		if (msg->content) free(msg->content);
		free(msg);
	}

	return !(response == STORAGE_ACK);
}

int clear_storage(struct mox_module *mod, int *addr, int n)
{
	mox_msg *msg = malloc(sizeof(mox_msg));
	unsigned response;
	int i;

	if (!msg) return NULL;

	msg->content = (unsigned char *)addr;
	msg->size = n * sizeof(int);
	msg->type = STORAGE_CLR;

	if (mox_req_com(mod->core_id, mod->mod_id)) {
		mox_comm_msg_send_thd(mod->core_id, *msg);
		free(msg);
		msg = mox_comm_msg_recv_thd(mod->core_id);
		mox_end_com(mod->core_id);
		if (msg) {
			response = msg->type;
			if (msg->content) free(msg->content);
			free(msg);
		}
	}

	return !(response == STORAGE_ACK);

}

